package com.taofuxn.admin.api.service;

import com.google.common.collect.Lists;
import com.taofuxn.admin.api.config.CurrentUser;
import com.taofuxn.admin.api.model.ResourceModel;
import com.taofuxn.admin.api.model.RoleModel;
import com.taofuxn.admin.api.model.SysUserModel;
import com.taofuxn.admin.api.model.response.SysUserPromiseResp;
import com.taofuxn.admin.common.exception.MvcCommonException;
import com.taofuxn.admin.common.exception.ExceptionEnum;
import com.taofuxn.admin.common.exception.UserException;
import com.taofuxn.admin.common.model.PageRequest;
import com.taofuxn.admin.common.model.PageResponse;
import com.taofuxn.admin.common.util.CheckUtil;
import com.taofuxn.admin.common.util.CodeUtil;
import com.taofuxn.admin.common.util.CopyUtils;
import com.taofuxn.admin.common.util.SecurityUtil;
import com.taofuxn.admin.dao.dto.ResourceDto;
import com.taofuxn.admin.dao.entity.*;
import com.taofuxn.admin.dao.opt.SysUserOpt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wong
 * @Date: 2020-11-27
 * @Version: 1.0
 */
@Service
public class SysUserConfigService {

    @Autowired
    private SysUserOpt sysUserOpt;


    /**
     * 查找用户
     *
     * @param loginName
     * @return
     */
    public SysUserModel getUserByLoginName(String loginName) {
        TbSysUser tbSysUser = sysUserOpt.getUserByAmount(loginName);
        if (null == tbSysUser) {
            return null;
        }
        return CopyUtils.copies(tbSysUser, new SysUserModel());
    }

    /**
     * 菜单树
     *
     * @return
     */
    public List<ResourceModel> getResourceList() {
        List<ResourceDto> dtos = sysUserOpt.selectResourceList();
        return dtos.stream().map(dto -> CopyUtils.copies(dto, new ResourceModel())).collect(Collectors.toList());
    }

    /**
     * 保存和更新菜单
     *
     * @param resource
     */
    public void saveOrUpdateResource(TbSysResource resource) {
        if (CheckUtil.checkIdForLong(resource.getParentId())) {
            TbSysResource parent = sysUserOpt.getResourceById(resource.getParentId());
            if (null == parent) {
                throw new MvcCommonException(ExceptionEnum.RESOURCE_NOT_FOUND_ERROR);
            }
        }

        if (CheckUtil.checkIdForLong(resource.getId())) {
            resource.setUpdateBy(CurrentUser.get().getLoginName());
            sysUserOpt.updateResource(resource);
        } else {
            resource.setCreateBy(CurrentUser.get().getLoginName());
            sysUserOpt.saveResource(resource);
        }
    }

    /**
     * 删除菜单
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteResource(Long id) {
        sysUserOpt.deleteResource(id);
    }


    /**
     * 保存用户
     *
     * @param sysUserModel
     */
    public void saveUser(SysUserModel sysUserModel) {
        String salt = CodeUtil.randomCode();
        String severPwd = SecurityUtil.md5(sysUserModel.getPassword(), salt);

        TbSysUser user = CopyUtils.copies(sysUserModel, new TbSysUser());
        user.setPassword(severPwd);
        user.setSalt(salt);

        sysUserOpt.saveUser(user);
    }

    /**
     *
     * 分页查找角色
     * @param pageParam
     * @return
     */
    public PageResponse<RoleModel> findRolePage(PageRequest<TbSysRole> pageParam) {
        long count = sysUserOpt.countRole(pageParam.getParam());
        if (count == 0) {
            return PageResponse.empty(pageParam.getPage(), pageParam.getLimit());
        }
        List<TbSysRole> tbSysRoles = sysUserOpt.selectRoleByPage(pageParam.getOffset(), pageParam.getLimit(), pageParam.getParam());
        //获取角色对应的资源
        List<RoleModel> roleModels = getRoleResourcesByRoleIds(tbSysRoles);
        return PageResponse.success(roleModels, pageParam.getPage(), pageParam.getLimit(), count);
    }


    private List<RoleModel> getRoleResourcesByRoleIds(List<TbSysRole> tbSysRoles) {
        Map<Long, List<TbSysRoleResource>> resourceRoleMap = sysUserOpt.selectResourceByRole(tbSysRoles.stream().map(TbSysRole::getId).collect(Collectors.toList()))
                .stream().collect(Collectors.groupingBy(TbSysRoleResource::getRoleId));

        return tbSysRoles.stream().map(role -> {
            RoleModel roleModel = CopyUtils.copies(role, new RoleModel());
            if (null != resourceRoleMap && resourceRoleMap.containsKey(role.getId())) {
                roleModel.setMenuIds(resourceRoleMap.get(role.getId()).stream().map(TbSysRoleResource::getResourceId).collect(Collectors.toList()));
            }
            return roleModel;
        }).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateRole(RoleModel role) {
        if (sysUserOpt.checkRepeaterRoleName(role.getName(), role.getId()) > 0) {
            throw new MvcCommonException("名称重复");
        }
        if (CheckUtil.checkIdForLong(role.getId())) {
            sysUserOpt.updateRole(role);
        } else {
            sysUserOpt.saveRole(role);
        }
        //处理资源权限
        sysUserOpt.updateRoleResource(role.getId(), role.getMenuIds());
    }

    public void deleteRole(Long roleId) {
        if (!CheckUtil.checkIdForLong(roleId)) {
            throw new MvcCommonException("角色ID为空");
        }
        sysUserOpt.deleteRoles(roleId);
    }

    /**
     * 分页查询用户列表
     *
     * @param pageRequest
     * @return
     */
    public PageResponse<SysUserPromiseResp> getUserPage(PageRequest<TbSysUser> pageRequest) {
        long count = sysUserOpt.countUser(pageRequest.getParam());
        if (0 == count) {
            return PageResponse.empty(pageRequest.getPage(), pageRequest.getLimit());
        }

        List<TbSysUser> tbSysUsers = sysUserOpt.selectUserBypage(pageRequest.getOffset(), pageRequest.getLimit(), pageRequest.getParam());

        List<Long> userIds = tbSysUsers.stream().map(TbSysUser::getId).collect(Collectors.toList());
        Map<Long, List<TbSysRole>> userRoles = sysUserOpt.getRolesByUserIds(userIds);

        List<SysUserPromiseResp> userPromiseResps = tbSysUsers.stream().map(u -> {
            SysUserPromiseResp userPromiseResp = CopyUtils.copies(u, new SysUserPromiseResp());
            if (Objects.nonNull(userRoles)) {
                List<TbSysRole> roles = userRoles.get(userPromiseResp.getId());
                if (!CollectionUtils.isEmpty(roles)) {
                    userPromiseResp.setRoles(roles.stream().map(r -> CopyUtils.copies(r, new RoleModel())).collect(Collectors.toList()));
                }
            }
            return userPromiseResp;
        }).collect(Collectors.toList());
        return PageResponse.success(userPromiseResps, pageRequest.getPage(), pageRequest.getLimit(), count);
    }

    @Transactional(rollbackFor = Exception.class)
    public void editUser(SysUserModel user, List<Long> roleIds) {
        if (!CheckUtil.checkIdForLong(user.getId())){
            throw new MvcCommonException("用户ID不能为空");
        }

        TbSysUser tbSysUser = CopyUtils.copies(user,new TbSysUser());
        sysUserOpt.updateUser(tbSysUser);
        sysUserOpt.deleteUserRoles(user.getId());
        sysUserOpt.addUserRoles(user.getId(),roleIds);
    }

    /**
     * 返回用户信息+角色+资源
     * @param userId
     * @return
     */
    public SysUserPromiseResp getUserDetailById(Long userId) {
        if (!CheckUtil.checkIdForLong(userId)){
            return null;
        }
        TbSysUser tbSysUser = sysUserOpt.getUserById(userId);
        if (null == tbSysUser){
            throw new UserException(ExceptionEnum.RESOURCE_NOT_FOUND_ERROR);
        }
        Map<Long,List<TbSysRole>> userRoleMap = sysUserOpt.getRolesByUserIds(Lists.newArrayList(userId));

        SysUserPromiseResp rs
         = CopyUtils.copies(tbSysUser,new SysUserPromiseResp());
        if (Objects.nonNull(userRoleMap) && userRoleMap.containsKey(userId)){
            List<TbSysRole> tbSysRoles = userRoleMap.get(userId);
            rs.setRoles(getRoleResourcesByRoleIds(tbSysRoles));
        }
        return rs;
    }

    public List<ResourceModel> getResourceById(List<Long> resourceIds) {
        if (CollectionUtils.isEmpty(resourceIds)){
            return Lists.newArrayList();
        }
        List<TbSysResource> resources = sysUserOpt.getResourceByIds(resourceIds);
        return parseResourceToTree(resources,0L);
    }

    /**
     * 解析成资源树
     * @param resources
     * @return
     */
    private List<ResourceModel> parseResourceToTree(List<TbSysResource> resources,Long parentId) {
        //子节点
        List<TbSysResource> nodes = resources.stream().filter(r-> Objects.equals(r.getParentId(), parentId)).collect(Collectors.toList());
        List<ResourceModel> result = new ArrayList<>();
        for (TbSysResource node : nodes) {
            ResourceModel resourceModel = CopyUtils.copies(node,new ResourceModel());
            result.add(resourceModel);
            //设置下级
            resourceModel.setChildren(parseResourceToTree(resources,node.getId()));
            //设置上级
            //resourceModel.setParent();
        }
        return result;
    }
}
